﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace Jemgine.Particles
{
    public class ParticleRenderer
    {
        Effect _effect;
        GraphicsDevice _device;

        public Matrix View { get; set; }
        public Matrix Projection { get; set; }
        public Matrix World { get; set; }

        EffectParameter epView;
        EffectParameter epWorld;
        EffectParameter epProjection;
        EffectParameter epTexture;

        DepthStencilState DepthState = new DepthStencilState
        {
            DepthBufferEnable = false
        };

        public void Initialize(GraphicsDevice Device, ContentManager Content)
        {
            _effect = Content.Load<Effect>("Engine.Content/ParticleEffect");
            _device = Device;

            epView = _effect.Parameters["View"];
            epWorld = _effect.Parameters["World"];
            epProjection = _effect.Parameters["Projection"];
            epTexture = _effect.Parameters["Texture"];
        }

        public void Draw(ParticleEffect Effect)
        {
            foreach (var Emitter in Effect.Emitters)
                Draw(Emitter);
        }

        public void Draw(Emitter emitter)
        {
            if (!emitter.Initialized || emitter._particleCount == 0) return;
            emitter.UpdateVertexBuffer();

            _device.DepthStencilState = DepthState;
            _device.RasterizerState = new RasterizerState { CullMode = Microsoft.Xna.Framework.Graphics.CullMode.None };

            epView.SetValue(View);
            epWorld.SetValue(World);
            epProjection.SetValue(Projection);
            epTexture.SetValue(emitter._texture);

            _device.SetVertexBuffer(emitter._vertexBuffer);
            _device.Indices = emitter._indexBuffer;

            switch (emitter.BlendMode)
            {
                case Emitter._BlendMode.Blend:
                    _effect.CurrentTechnique = _effect.Techniques["prtBlend"];
                    break;
                case Emitter._BlendMode.Add:
                    _effect.CurrentTechnique = _effect.Techniques["prtAdd"];
                    break;
            }

            foreach (EffectPass pass in _effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                _device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, emitter._particleCount * 4,
                    0, emitter._particleCount * 2);
            }

            _device.SetVertexBuffer(null);
            _device.Indices = null;
        }
    }
}
